/*
 * @Author: mark
 * @Date: 2024-02-18 21:10:41
 * @LastEditors: mark
 * @LastEditTime: 2024-02-25 22:10:46
 * @FilePath: /自研/RuoYi_egg/ruoyi-egg/app/service/test.js
 * @Description:
 *
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
 */
const path = require("path");
const fs = require("fs");
const { fileDisplay } = require("../utils/public");
const Service = require("egg").Service;
let unDetailObj = [];
const pathMapTable = {
  "system/config/": "sys_config",
  "system/dept/": "sys_dept",
  "system/log/": "sys_job_log",
  "system/menu/": "sys_menu",
  "system/notice/": "sys_notice",
  "system/roleDept/": "sys_role_dept",
  "system/roleMenu/": "sys_role_menu",
  "system/sysDictData/": "sys_dict_data",
  "system/sysDictType/": "sys_dict_type",
  "system/sysLogininfor/": "sys_logininfor",
  "system/sysOperLog/": "sys_oper_log",
  "system/sysPost/": "sys_post",
  "system/sysRole/": "sys_role",
  "system/sysUserRole/": "sys_user_role",
  "system/user/": "sys_user",
  "system/userPost/": "sys_user_post",
  "system/userRole/": "sys_user_role",
};

class TestService extends Service {
  constructor(ctx) {
    super(ctx);
    this.session = ctx.session;
    this.ResponseCode = ctx.response.ResponseCode;
    this.ServerResponse = ctx.response.ServerResponse;
    this.objUnderlineToHump = ctx.objUnderlineToHump;
    this.underlineToHump = ctx.underlineToHump;
    this.objHumpToUnderline = ctx.objHumpToUnderline;
    this.underlineToHump = ctx.underlineToHump;
    this.toInt = ctx.toInt;
    this.ctx = ctx;
    this.GenTable = ctx.model.GenTable;
    this.GenTableColumn = ctx.model.GenTableColumn;
  }
  convertMySQLTypeToJSType(mysqlType) {
    mysqlType = mysqlType.toLowerCase();
    switch (mysqlType) {
      case "int":
      case "tinyint":
      case "smallint":
      case "mediumint":
      case "bigint":
      case "number":
        return "number";
      case "float":
      case "double":
      case "decimal":
        return "number";
      case "char":
      case "varchar":
      case "text":
      case "longtext":
      case "string":
        return "string";
      case "date":
      case "datetime":
      case "timestamp":
        // return "Date";
        return "string";
      default:
        return "string";
    }
  }
  /**
   * 自动生成swagger
   */
  async autoFunction(app) {
    // 更新gentablecolumn中的java——type参数
    // let columns = await this.GenTableColumn.findAll({ raw: true });
    // columns = columns.map((item) => {
    //   item.java_type = this.convertMySQLTypeToJSType(item.java_type);
    //   return item;
    // });
    // await this.GenTableColumn.bulkCreate(columns, {
    //   updateOnDuplicate: ["java_type"],
    // });
    // await this.autoParams(app);
    // await this.autoController();
    // await this.createResponse()
  }

  /**
   * 生成接口请求的备注
   */
  async autoParams(app) {
    //获取数据库中字段的数据
    let tablesColumn = await this.GenTable.findAll({
      include: [
        {
          model: this.GenTableColumn,
        },
      ],
    });
    tablesColumn = tablesColumn.map((item) => {
      item = item.dataValues;
      item.gen_table_columns = item.gen_table_columns.map((item2) => {
        return item2.dataValues;
      });
      return item;
    });

    let fileData = await this.getAllFileData("./app/router");
    delete fileData["router/system/log.js"];

    let newfile = {};
    for (var key in fileData) {
      // if (key.indexOf("monitor/job.js") > -1) {
      newfile[key] = fileData[key];
      // }
    }
    fileData = newfile;
    // fileData = {
    //   "router/system/config.js": fileData["router/system/config.js"],
    // };
    for (var key in fileData) {
      let newData = fileData[key].split("//");
      newData = newData.filter((item) => item.indexOf("module.exports") == -1);
      newData = newData.map((item) => {
        item = item.replace(/\n/g, "");
        item = item.split("app.router.");
        let remark = item[0];
        item = item[1].split("(");
        let methods = item[0];
        item = item[1].split('"');
        let router = item[1];
        item = item[2].split(",");
        item = item[1].split(")");
        let path = item[0].replace(/\s/g, "").replace(/\./g, "/");
        let name = router
          .split("/:")[0]
          .split("/")
          .filter((item) => item != 1);
        let change = path.split("/");
        let func = change[change.length - 1];
        name = name.join("_");
        name = "_" + name;
        name = this.underlineToHump(name);
        if (router.indexOf(":") > -1) {
          router = router.split("/");
          router = router.map((item) => {
            if (item.indexOf(":") > -1) {
              item = item.split(":")[1];
              item = "{" + item + "}";
            }
            return item;
          });
          router = router.join("/");
        }
        path = path.split("/");
        path.pop();
        path = path.join("/");

        //查找相应的传递参数
        // let tableName = "";
        let checkName = router.split("/");
        checkName.pop();
        checkName = checkName.join("/");
        checkName = checkName.substr(1);
        checkName = checkName + "/";
        let is_query = "";
        let is_edit = "";
        let is_insert = "";
        if (pathMapTable[checkName]) {
          let tables = tablesColumn.filter(
            (item) => item.table_name == pathMapTable[checkName]
          );
          is_query = tables[0].gen_table_columns.filter(
            (item) => item.is_query
          );
          is_edit = tables[0].gen_table_columns.filter((item) => item.is_edit);
          is_insert = tables[0].gen_table_columns.filter(
            (item) => item.is_insert && !(item.is_increment && item.is_pk)
          );
        }
        return {
          path,
          router,
          methods,
          remark,
          name,
          func,
          is_query,
          is_edit,
          is_insert,
        };
      });

      let filterData = [];
      newData.forEach((item) => {
        let check = false;
        filterData.forEach((item2) => {
          if (item.func == item2.func) {
            check = true;
          }
        });
        if (!check) {
          filterData.push(item);
        }
      });
      newData = filterData;

      let publicpath = __filename;
      publicpath = publicpath.replace(/\\/g, "/");
      publicpath = publicpath.split("/app/")[0];
      publicpath += "/";
      //读取相应的controller文件 并且写入
      for (let i = 0; i < newData.length; i++) {
        let file = fs.readFileSync(
          publicpath + newData[i].path + ".js",
          "utf8"
        );
        let old = file;
        file = file.split(`async ${newData[i].func}`);
        let setSwagger = `/**
   * @summary ${newData[i].remark.replace(/\r/g, "")}
   * @description ${newData[i].remark.replace(/\r/g, "")}
   * @Router ${newData[i].methods} ${newData[i].router}\r\n`;
        if (newData[i].func == "list") {
          setSwagger += `   * @request query string pageNum 页码 默认 1
   * @request query string pageSize 单页数量 默认 10\r\n`;
        }
        //需要进行校验的数据
        let valiData = "";
        switch (newData[i].methods) {
          case "get":
            if (!newData[i].is_query) break;
            if (newData[i].func == "list" || newData[i].func == "detail") {
              valiData += `// 定义请求接口的请求参数规则
const queryRule = {\r\n`;
              newData[i].is_query.forEach((item) => {
                setSwagger += `   * @request query string ${this.underlineToHump(
                  item.column_name
                )} ${item.column_comment}\r\n`;
                valiData += `  ${this.underlineToHump(
                  item.column_name
                )}: { type: "string", required: false },\r\n`;
              });
              valiData += "};\r\n";
            }
            break;
          case "post":
            if (!newData[i].is_insert) break;
            if (newData[i].func == "create") {
              valiData += `// 定义创建接口的请求参数规则
const createRule = {\r\n`;
              newData[i].is_insert.forEach((item) => {
                setSwagger += `   * @request query ${
                  item.java_type
                } ${this.underlineToHump(item.column_name)} ${
                  item.column_comment
                }\r\n`;
                valiData += `  ${this.underlineToHump(
                  item.column_name
                )}: { type: "${item.java_type}", required: ${
                  item.is_required ? true : false
                } },\r\n`;
              });
              valiData += "};\r\n";
            }
            break;
          case "put":
            if (!newData[i].is_edit) break;
            if (newData[i].func == "update") {
              valiData += `// 定义更新接口的请求参数规则
const updateRule = {\r\n`;
              newData[i].is_edit.forEach((item) => {
                setSwagger += `   * @request query ${
                  item.java_type
                } ${this.underlineToHump(item.column_name)} ${
                  item.column_comment
                }\r\n`;
                valiData += `  ${this.underlineToHump(
                  item.column_name
                )}: { type: "${item.java_type}", required: ${
                  item.is_required ? true : false
                } },\r\n`;
              });
              valiData += "};\r\n";
            }
            break;
          default:
            break;
        }

        if (newData[i].methods == "get" && newData[i].func != "detail") {
          setSwagger += `   * @response 200 ${newData[i].name} 操作成功\r\n`;
        } else {
          setSwagger += `   * @response 200   操作成功\r\n`;
        }

        setSwagger += "   */\r\n";
        if (valiData) {
          if (newData[i].func == "list" || newData[i].func == "detail") {
            if (file[0].indexOf("queryRule") == -1) {
              file[0] = file[0]
                .split(
                  `/**
 * @Controller`
                )
                .join(
                  valiData +
                    `\r\n/**
 * @Controller`
                );
            }
          }
        }
        setSwagger += `  async ${newData[i].func}`;
        if (old.indexOf(setSwagger) == -1) {
          file = file.join(setSwagger);
          if (valiData) {
            file = file.split(`  async ${newData[i].func}(ctx) {`);
            switch (newData[i].methods) {
              case "get":
                file[1] =
                  "\r\n    ctx.validate(queryRule, ctx.request.query);" +
                  file[1];
                break;
              case "post":
                file[1] =
                  "\r\n    ctx.validate(createRule, ctx.request.body);" +
                  file[1];
                break;
              case "put":
                file[1] =
                  "\r\n    ctx.validate(editRule, ctx.request.body);" + file[1];
                break;
              default:
                break;
            }
            file = file.join(`  async ${newData[i].func}(ctx) {`);
          }
          fs.writeFileSync(publicpath + newData[i].path + ".js", file);
        }
      }
    }
  }

  /**
   * 获取某个相对路径下的所有文件
   */
  async getAllFileData(path) {
    let data = fileDisplay(path);
    let publicpath = __filename;
    publicpath = publicpath.replace(/\\/g, "/");
    publicpath = publicpath.split("/app/")[0];
    publicpath += "/";
    let fileDataObj = {};
    for (var j = 0; j < data.length; j++) {
      data[j] = data[j].replace(/\\/g, "/");
      data[j] = publicpath + data[j];
      let filedata = fs.readFileSync(data[j], "utf8");
      fileDataObj[data[j].split("/app/")[1]] = filedata;
    }
    // let data2 = {};
    // for (var key in fileDataObj) {
    //   let key2 = key.split("router/")[1];
    //   key2 = key2.split(".js")[0];
    //   let key3 = key2
    //     .split("/")
    //     .join("_")
    //     .replace(/system/g, "sys");
    //   data2[key2] = key3;
    // }
    // console.log(JSON.stringify(data2));
    return fileDataObj;
  }

  /**
   * 自动生成controller
   */
  async autoController() {
    //获取数据库中的数据
    let tables = await this.GenTable.findAll({ raw: true });

    //读取router下所有的文件
    //根据class SysJobController extends Controller 添加在这行上面
    let data = fileDisplay("./app/controller");
    let publicpath = __filename;
    publicpath = publicpath.replace(/\\/g, "/");
    publicpath = publicpath.split("/app/")[0];
    publicpath += "/";
    for (var j = 0; j < data.length; j++) {
      data[j] = data[j].replace(/\\/g, "/");
      data[j] = publicpath + data[j];
      let filedata = fs.readFileSync(data[j], "utf8");
      filedata = filedata.split("class ");
      let name = filedata[1].split("Controller extends")[0];
      let setName = tables.filter((item) => item.class_name == name);
      if (setName.length) {
        name = setName[0].function_name;
      }
      if (filedata[0].indexOf(" * @Controller") == -1) {
        filedata[0] =
          filedata[0] +
          `/**
 * @Controller ${name}
 */\r\n`;
        filedata = filedata.join("class ");
        fs.writeFileSync(data[j], filedata);
      }
    }
  }

  /**
   * 生成接口返回的注释
   */
  async createResponse() {
    let debug = "";
    //读取router下所有的文件
    let data = fileDisplay("./app/router");
    let publicpath = __filename;
    publicpath = publicpath.replace(/\\/g, "/");
    publicpath = publicpath.split("/app/")[0];
    publicpath += "/";
    let obj = [];
    for (var j = 0; j < data.length; j++) {
      data[j] = data[j].replace(/\\/g, "/");
      data[j] = publicpath + data[j];
      let filedata = fs.readFileSync(data[j], "utf8");
      //找到所有的get请求
      filedata = filedata.split(";");
      let newData = [];
      filedata.forEach((fd) => {
        let pushData;
        try {
          if (fd.indexOf(".router.get") > -1) {
            pushData = fd.split('basicUrl + "')[1].split('"')[0];
            pushData = pushData.split("/");
            pushData = pushData.map((pushDataItem) => {
              if (pushDataItem.indexOf(":") > -1) {
                return 1;
              }
              return pushDataItem;
            });
            pushData = pushData.join("/");
            newData.push(pushData);
          }
        } catch (error) {
          console.log("err***************", error);
        }
      });
      let newSetData = [];
      for (let i = 0; i < newData.length; i++) {
        let res;
        let pathAdd = newData[i];
        if (pathAdd == "/monitor/cache/getValue/1/1") {
          pathAdd = "/monitor/cache/getValue/sys_dict/sys_user_sex";
        }
        if (pathAdd == "/system/dept/1") {
          pathAdd = "/system/dept/100";
        }
        if (pathAdd == "/system/roleDept/1") {
          pathAdd = "/system/roleDept/2";
        }
        if (pathAdd == "/system/roleMenu/1") {
          pathAdd = "/system/roleMenu/2";
        }
        if (pathAdd == "/system/notice/1") {
          pathAdd = "/system/notice/2";
        }
        if (pathAdd == "/tool/gen/db/list") {
          pathAdd = "/tool/gen/db/list?pageNum=1&pageSize=1";
        }
        if (pathAdd == "/tool/gen/1") {
          pathAdd = "/tool/gen/14";
        }
        if (pathAdd == "/system/role/authUser/1") {
          pathAdd =
            "/system/role/authUser/allocatedList?pageNum=1&pageSize=1&roleId=1";
        }
        if (pathAdd == "/log") {
          break;
        }
        //发送请求获取参数
        res = await this.ctx.curl("http://localhost:10020" + pathAdd, {
          dataType: "json",
          headers: {
            Authorization:
              "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJOYW1lIjoiYWRtaW4iLCJpYXQiOjE3MDgzMzM1NzMsImV4cCI6MjAyMzY5MzU3M30.oN9axQYVnLK1MgeV7UJ5RihFvETyCh1hKUL_bY39UDA",
          },
        });
        res = res.data;
        if (res.code == 200) {
          let name = newData[i].split("/");
          name = name.filter((item) => item != 1);
          name = name.join("_");
          name = this.underlineToHump(name);
          res = this.formatResponseForSwagger(res, name);
          newSetData.push({
            name,
            path: newData[i],
            res,
          });
          while (unDetailObj.length) {
            let detail = JSON.parse(JSON.stringify(unDetailObj));
            detail.forEach((item) => {
              item = JSON.parse(item);
              newSetData.push({
                name: item.name,
                path: newData[i],
                res: this.formatResponseForSwagger(item.value, item.name),
              });
            });
            unDetailObj = unDetailObj.filter(
              (item2) => detail.indexOf(item2) == -1
            );
          }
        } else {
          debug += `${newData[i]}\r\n${JSON.stringify(res)}\r\n\r\n`;
        }
      }
      obj.push({
        path: data[j],
        mark: data[j].split("/router")[1],
        data: newSetData,
      });
    }
    //写入debug
    let debugpath = __filename;
    debugpath = debugpath.replace(/\\/g, "/");
    debugpath = debugpath.split("app/")[0];
    fs.writeFileSync(debugpath + "debug.js", debug);
    //读取router下的所有路由
    obj.forEach((item) => {
      try {
        let path = item.path.split("/router/").join("/contract/");
        let dir = path.split("/contract/")[1];
        dir = dir.split("/");
        dir.forEach((item, index) => {
          let dirSet = path.split("/contract/")[0] + "/contract/";
          for (var i = 0; i <= index; i++) {
            dirSet += `${dir[i]}/`;
          }
          dirSet = dirSet.slice(0, -1);
          if (item.indexOf(".") == -1 && !fs.existsSync(dirSet)) {
            fs.mkdirSync(dirSet);
          }
        });
        let fileData = "module.exports = {\r\n";
        item.data.forEach((dataIn) => {
          if (dataIn.res) {
            fileData += `${dataIn.name}:{\r\n${JSON.stringify(dataIn.res).slice(
              1,
              -1
            )}\r\n},\r\n`;
          }
        });
        fileData += "\r\n}";
        if (!fs.existsSync(path)) {
          fs.writeFileSync(path, fileData);
        }
      } catch (err) {
        console.error(`无法创建文件 ${path}:`, err);
      }
    });
  }

  /**
   * 我们需要将json转换为egg-swagger-doc期望的格式
   * @param {*} jsonData
   * @param {*} name
   * @returns
   */
  formatResponseForSwagger(jsonData, name) {
    // 递归遍历JSON对象并格式化每个字段
    function formatField(field) {
      // 根据字段类型返回不同的格式
      switch (typeof field) {
        case "number":
          return { type: "number", example: field };
        case "string":
          return { type: "string", example: field };
        case "boolean":
          return { type: "boolean", example: field };
        case "object":
          if (Array.isArray(field)) {
            if (!field[0]) {
              return {
                type: "string",
                example: "[]",
              };
            }
            unDetailObj.push(
              JSON.stringify({
                name: name + "_item",
                value: field[0],
              })
            );
            // 处理数组类型的字段
            return {
              type: "array",
              itemType: field[0] ? name + "_item" : "null",
              // items: field.length > 0 ? formatField(field[0]) : {},
            };
          } else {
            if (!field) {
              return { type: "string", example: "null" };
            }
            // 处理对象类型的字段
            let formattedObject = {
              type: "object",
              properties: {},
            };
            for (let key in field) {
              formattedObject.properties[key] = formatField(field[key]);
            }
            return formattedObject;
          }
        default:
          return { type: "string", example: "null" };
      }
    }

    // 格式化整个JSON对象
    let formattedResponse = {};
    for (let key in jsonData) {
      formattedResponse[key] = formatField(jsonData[key]);
    }

    return formattedResponse;
  }
}

module.exports = TestService;
